package com.financing.platform.web.api;

import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.financing.platform.dto.FpFileRecordDTO;
import com.financing.platform.dto.ProductAttachmentDTO;
import com.financing.platform.dto.ProjectDTO;
import com.financing.platform.service.IFpFileRecordService;
import com.financing.platform.service.IProjectService;

import com.financing.platform.util.AliyunOssUtil;
import net.sf.json.JSONObject;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import com.financing.platform.common.ResultCode;
import com.financing.platform.common.ResultMap;
import com.financing.platform.common.ResultMap.STATUS;
import com.financing.platform.util.RandomUtils;
import com.financing.platform.util.StringUtil;

@Controller("fileUploadController")
@RequestMapping("/api")
public class FileUploadController  extends BaseAction{

	@Value("#{settings['fileBaseDir']}")
	private String fileBaseDir;
	
	private Map<String,String> fileDir = new HashMap<String,String>();
	
	private List<String> allowList;
	
	@Value("#{settings['fileTypeDir']}")
	private String fileTypeDir;
	
	@Value("#{settings['fileAllowTypes']}")
	private String fileAllowTypes;

	@Value("#{settings['AliyunOss']}")
	private Boolean aliyunOss;
	@Autowired
	private IFpFileRecordService fileRecordService;//文件记录服务
	Logger logger = Logger.getLogger(getClass());

	@Autowired
	private IProjectService projectServiceImpl;

	@RequestMapping("/fileUpload.shtml")
	public ResultMap fileUpload(HttpServletRequest request, HttpServletResponse response){
		ResultMap result = new ResultMap();
		String filePath = getFilePath(request);
		if(StringUtil.isNullOrEmptyStr(filePath)){
			log.warn("file type not exist!");
			result.setStatus(STATUS.ERROR);
			result.setStatusCode(ResultCode.STATUS_CODE_SAVE_FILE_DIR_ERROR);
			getJsonData(request,response,result);
			return null;
		}
		
		try{
			CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
			if(multipartResolver.isMultipart(request))
	        {
	            //将request变成多部分request
	            MultipartHttpServletRequest multiRequest=(MultipartHttpServletRequest)request;
	           //获取multiRequest 中所有的文件名
	            Map<String,MultipartFile> mutipartFileMap = multiRequest.getFileMap();
	             
	            Iterator<Entry<String, MultipartFile>> mutipartFileIterator =  mutipartFileMap.entrySet().iterator();
	            while(mutipartFileIterator.hasNext())
	            {
	            	Entry<String, MultipartFile> entry = mutipartFileIterator.next();
	                MultipartFile file=entry.getValue();
	                if(!isAllowFileType(file.getContentType())){
	                	log.error("upload file type error!");
	                	result.setStatus(STATUS.ERROR);
	        			result.setStatusCode(ResultCode.STATUS_CODE_FILE_TYPE_ERROR);
	        			getJsonData(request,response,result);
	        			return null;
	                }
	                if(file!=null && (!file.isEmpty()) &&  entry.getKey() !=null && entry.getKey().length()>0)
	                {
						//文件类型
						String fileType = request.getParameter("fileType");

						//文件名称
						String  originalFilename = file.getOriginalFilename();

						//目录
						StringBuffer fileFull = new StringBuffer();
						fileFull.append(filePath)
								.append("/")
								.append(StringUtil.dateNowStr("yyyyMMdd"));
						//文件全路径
						StringBuffer fileFullPath = new StringBuffer(fileFull.toString());

						//名称
						String randomName = fileType+"_"+System.currentTimeMillis()+"";

						//后缀
						String houzhui = originalFilename.substring(originalFilename.lastIndexOf("."));
						fileFullPath.append("/")
								.append(randomName)
								.append(houzhui);
						//.append(file.getOriginalFilename().replaceAll(" ", "").replaceAll(",", ""));

						//判断 是否-oss
						logger.info("fileUpload.shtml  AliyunOss:"+aliyunOss);
						if(!aliyunOss) {
							//目录
							File dir = new File(fileBaseDir + fileFull.toString());
							if (!dir.exists()) {
								dir.mkdirs();
							}
							//上传 文件
							File fileTmp = new File(fileBaseDir + fileFullPath.toString());

							if (!fileTmp.exists()) {
								fileTmp.createNewFile();
								logger.info("create new file !");
							}
							file.transferTo(fileTmp);
						}else{
							AliyunOssUtil.writeFile(file.getInputStream(), fileFullPath.toString().substring(1,fileFullPath.toString().length()));
						}


						//添加- 文件记录
						String refid = ServletRequestUtils.getStringParameter(request, "refid");
						FpFileRecordDTO fileRecord = new FpFileRecordDTO();

						fileRecord.setType(fileType);
						fileRecord.setRefid(refid);
						fileRecord.setFileSuffix(houzhui);
						fileRecord.setFileName(originalFilename);
						fileRecord.setLogicName(randomName+houzhui);
						fileRecord.setLogicFullpath(fileFullPath.toString());
						fileRecordService.insert(fileRecord);
	        			
	        			result.setStatus(STATUS.SUCCESS);
	        			result.setStatusCode(ResultCode.RESULT_CODE_SUCCESS);
						result.setAttribute("fileType", file.getContentType());
						result.setAttribute("fName", originalFilename);
						result.setAttribute("fileUrl",  fileFullPath.toString());
						result.setAttribute("fileid", fileRecord.getId());
	        			
	        			getJsonData(request,response,result);
	        			return null;
	                }
	                 
	            }
	           
	        }
		}catch(Exception e){
			log.error("upload file error:",e);
			result.setStatus(STATUS.ERROR);
			result.setStatusCode(ResultCode.RESULT_CODE_SYSTEM_ERROR);
			getJsonData(request,response,result);
			return null;
		}
		
		log.warn("no file upload!");
		result.setStatus(STATUS.ERROR);
		result.setStatusCode(ResultCode.STATUS_CODE_NO_FILE_UPLOAD);
		
		getJsonData(request,response,result);
		
		return null;
		
		
		
	}

	@Autowired
	private void setDir(){
		String[] fileTypes = fileTypeDir.split(";");
		for(String tmp : fileTypes){
			String[] tmpTypes = tmp.split(":");
			if(tmpTypes.length==2){
				fileDir.put(tmpTypes[0], tmpTypes[1]);
			}
		}
		
		//注入允许上传的文件类型
		allowList = new ArrayList<String>();
		String[] allowTypes = fileAllowTypes.split(",");
		for(String type : allowTypes){
			allowList.add(type);
		}
		
	}
	
	/**
	 * 
	 * @Title: getFilePath
	 * @Description: 根据文件类型选择上传文件路径 
	 * @param @param request
	 * @param @return   
	 * @return String   
	 * @throws
	 */
	private String getFilePath(HttpServletRequest request){
		String fileType = request.getParameter("fileType");
		if(StringUtil.isNullOrEmptyStr(fileType)){
			fileType = "common";
		}
		return fileDir.get(fileType);
	}
	/**
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/productDownload.shtml")
	public String downloadFile(HttpServletRequest request, HttpServletResponse response,Integer id,Integer pId)
			throws Exception {


		//打zip
        if(pId != null && pId>0){
			List<ProductAttachmentDTO>  attachments =	projectServiceImpl.queryProductAttachments(pId);
			
			
			//多个就打zip
			ZipOutputStream zos = null;
			String zipName = "productFile"+pId+".zip";
			
			
			try{
				//查询产品名字
				ProjectDTO projectDTO=new ProjectDTO();
				projectDTO.setId(pId);
				ProjectDTO queryProject = projectServiceImpl.queryProject(projectDTO);
				String getpName = queryProject.getpName();
				if(StringUtils.isNotBlank(getpName)){
					zipName=getpName+".zip";
				}
				response.reset();
				response.setHeader("Content-Disposition","attachment; filename="+new String(zipName.getBytes("gb2312"), "ISO8859-1" ));

				logger.info("===ZipOutputStream ===> zipName:"+zipName);
				zos = new ZipOutputStream(response.getOutputStream());
				for (ProductAttachmentDTO bean: attachments){
					String fpath = bean.getfPath();
					String fileName = fpath.substring(fpath.lastIndexOf("/") + 1);
					fpath =  fpath.substring(0,fpath.lastIndexOf("/")+1);

					String downLoadPath = fileBaseDir + fpath+URLEncoder.encode(fileName,"utf-8");

					logger.info("===ZipOutputStream ===> downLoadPath:"+downLoadPath);
					logger.info("===ZipOutputStream ===> fileName:"+bean.getfName());

					//判断 是否-oss
					if(!aliyunOss){
						doCompress( new FileInputStream(new File(downLoadPath)),bean.getfName(),zos);
					}else{
						doCompress( AliyunOssUtil.readFile(bean.getfPath().substring(1,bean.getfPath().length())),bean.getfName(),zos);
					}

					response.flushBuffer();
				}
			}catch(Exception e){
				log.error("faUserCsv error !",e);
			}finally {
				if (zos != null) {
					try {
						zos.close();
					} catch (IOException e) {
					}
				}
			}
			return null;
		}


		ProductAttachmentDTO f = projectServiceImpl.queryProductAttachmentsForId(id);

		if(f!=null) {///lanmo/upload/lantu/Id_filerecord00000003_1423196856213.jpg
			String ctype = f.getfType();
			String fullpath =fileBaseDir + f.getfPath();
			OutputStream os = response.getOutputStream();
			String agent = request.getHeader("USER-AGENT");
			String downLoadName = null;
			String filename = f.getfName();
			if (null != agent && -1 != agent.indexOf("MSIE"))   //IE
			{
				downLoadName = java.net.URLEncoder.encode(filename, "UTF-8");
			}
			else if (null != agent && -1 != agent.indexOf("Mozilla")) //Firefox
			{
				downLoadName = new String(filename.getBytes("UTF-8"),"iso-8859-1");
			}
			else
			{
				downLoadName = java.net.URLEncoder.encode(filename, "UTF-8");
			}
			try {
				response.reset();
				//     			response.setHeader("Content-Disposition", "attachment; filename="+downLoadName);
				response.setContentType(ctype);
				if(!aliyunOss) {
					os.write(FileUtils.readFileToByteArray(new File(fullpath)));
					os.flush();
				}else{
					AliyunOssUtil.readFile( f.getfPath().substring(1, f.getfPath().length()),os);
				}

			} finally {
				if (os != null) {
					os.close();
				}
			}
		}
		return null;
	}

	public static void doCompress(InputStream inputStream, String fileName ,ZipOutputStream out) throws IOException{
		if( inputStream != null ){
			byte[] buffer = new byte[1024];
			out.putNextEntry(new ZipEntry(fileName));
			int len = 0 ;
			// 读取文件的内容,打包到zip文件
			while ((len = inputStream.read(buffer)) > 0) {
				out.write(buffer, 0, len);
			}
			out.flush();
			out.closeEntry();
			inputStream.close();
		}
	}
	/**
	 * 
	 * @Title: isAllowFileType
	 * @Description: 判断文件类型是否未允许的类型 
	 * @param @param type
	 * @param @return   
	 * @return boolean   
	 * @throws
	 */
	private boolean isAllowFileType(String type){
		return allowList.contains(type.toLowerCase());
	}
	private void getJsonData(HttpServletRequest request,HttpServletResponse response,Object result)
    {
        String callback = null;

        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = null;

        if(result == null)
        {
            try
            {
                String jsonStr = "";
                out = response.getWriter();
                out.println(jsonStr);
            }
            catch (Exception e)
            {
            }
            finally
            {
                if (null != out)
                {
                    out.close();
                }
            }
        }

        try
        {

            JSONObject json = JSONObject.fromObject(result);
            String jsonStr = json.toString();
            if(!StringUtil.isNullOrEmptyStr(callback))
            {
                jsonStr =  callback + "("+ jsonStr +")";
            }


            out = response.getWriter();
            out.print(jsonStr);
        }
        catch (Exception e)
        {
        }
        finally
        {
            if (null != out)
            {
                out.close();
            }
        }
    }



}
